﻿namespace Okazuki.BehaviorSupport.Design.Commons
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Windows.Design.Interaction;
    using Microsoft.Windows.Design;
    using Microsoft.Windows.Design.Model;
    using System.Windows;

    public abstract class PrimarySelectionContextMenuProviderBase : PrimarySelectionContextMenuProvider
    {
        private Type behaviorType;

        private Type triggerType;

        private Type actionType;

        public PrimarySelectionContextMenuProviderBase(
            Type behaviorType, 
            Type triggerType, 
            Type actionType)
        {
            this.behaviorType = behaviorType;
            this.triggerType = triggerType;
            this.actionType = actionType;

            InitializeMenu();
        }

        private void InitializeMenu()
        {
            var addBehavior = new MenuAction("Add Behavior...");
            addBehavior.Execute += new EventHandler<MenuActionEventArgs>(addBehavior_Execute);
            this.Items.Add(addBehavior);

            var addAction = new MenuAction("Add Action...");
            addAction.Execute += new EventHandler<MenuActionEventArgs>(addAction_Execute);
            this.Items.Add(addAction);
        }

        private void addAction_Execute(object sender, MenuActionEventArgs e)
        {
            var typeResolver = new AssemblyReferencesTypeResolver(e.Context.Items.GetValue<AssemblyReferences>());

            var selected = e.Selection.PrimarySelection;
            if (selected == null)
            {
                return;
            }
            var dialog = new ActionSelectWindow(
                typeResolver.ResolveInheritTypes(triggerType),
                typeResolver.ResolveInheritTypes(actionType));
            if (dialog.ShowDialog() != true)
            {
                return;
            }

            var selectedTypes = dialog.SelectedTriggerAndAction;
            if (selectedTypes == null)
            {
                return;
            }

            var trigger = TypeBuilder.CreateTriggerAction(
                selectedTypes.Item1,
                selectedTypes.Item2);
            if (trigger == null)
            {
                return;
            }
            using (var scope = selected.BeginEdit())
            {
                var triggers = (ModelItemCollection)selected.Properties[Identifiers.TriggersProperty].Collection;
                if (triggers == null)
                {
                    MessageBox.Show("I can't get Interacton.Triggers property.");
                    return;
                }

                triggers.Add(trigger);
                scope.Complete();
            }
        }

        private void addBehavior_Execute(object sender, MenuActionEventArgs e)
        {
            var typeResolver = new AssemblyReferencesTypeResolver(e.Context.Items.GetValue<AssemblyReferences>());
            
            var selected = e.Selection.PrimarySelection;
            if (selected == null)
            {
                return;
            }
            var dialog = new BehaviorSelectWindow(typeResolver.ResolveInheritTypes(this.behaviorType));
            if (dialog.ShowDialog() != true)
            {
                return;
            }

            var selectedType = dialog.SelectedBehaviorType;
            if (selectedType == null)
            {
                return;
            }

            var behavior = TypeBuilder.CreateBehavior(selectedType);

            using (var scope = selected.BeginEdit())
            {
                var behaviors = (ModelItemCollection)selected.Properties[Identifiers.BehaviorsProperty].Collection;
                if (behaviors == null)
                {
                    MessageBox.Show("I can't get Interacton.Behaviors property.");
                    return;
                }

                behaviors.Add(behavior);
                scope.Complete();
            }
        }
    }
}
